-- Scorchio!
-- A multi-mob fire vulnerability manager
-- Ennui@Bloodhoof-EU
-- Email: ennuilg@gmail.com
-- Based on: ScorchWatch by Liccee

local SM = AceLibrary("SharedMedia-1.0")
local PC = AceLibrary("PaintChips-2.0")
local L = AceLibrary("AceLocale-2.2"):new("Scorchio")

local SB = "Scorch_Bars"
local MOBNAME = 1
local REFRESHTIME = 2
local SCORCHSTACK = 3
local CASTS = 4

local playerName = UnitName("player")
local versionNumber = "0.60"
local testBars = false
local mageList = { }
local impScorch = nil

local options = { 
    handler = Scorchio,
    type = 'group',
    args = {
        baroptions = {
            type = 'group',
            name = L["Bar Options"],
            desc = L["Bar Options"],
            args = {
                anchor = {
                    type = 'group',
                    name = L["Anchor"],
                    desc = L["Manage anchor and test bars"],
                    order = 10,
                    args = {
                        anchortoggle = {
                            type = 'execute',
                            name = L["Toggle"],
                            desc = L["Shows/hides the dragable anchor and test bars"],
                            func = "ToggleAnchor",
                            order = 101
                        },
                        anchorreset = {
                            type = 'execute',
                            name = L["Reset Position"],
                            desc = L["Reset anchor position to center of screen"],
                            func = "ResetAnchor",
                            order = 102,
                        },
                    },
                },
                growup = {
                    type = 'toggle',
                    name = L["Grow Up"],
                    desc = L["If checked, bar will stack above the anchor, not below"],
                    get = function()
                        return Scorchio.db.profile.growUp
                    end,
                    set = function(v)
                        Scorchio.db.profile.growUp = not Scorchio.db.profile.growUp
                        Scorchio:SetGrowUp()
                    end
                },
				barwidth = {
					type = 'range',
					name = L["Width"],
					desc = L["Change the width of the bars"],
                    order = 120,
					get = function()
						return Scorchio.db.profile.baroptions.width
					end,
					set = function(v)
						Scorchio.db.profile.baroptions.width = v
                        if testBars then Scorchio:ShowTestBars() end                        
					end,
					min = 24,
					max = 512,
					step = 8,
				},
				barheight = {
					type = 'range',
					name = L["Height"],
					desc = L["Change the height of the bars"],
                    order = 121,
					get = function()
						return Scorchio.db.profile.baroptions.height
					end,
					set = function(v)
						Scorchio.db.profile.baroptions.height = v
                        if testBars then Scorchio:ShowTestBars() end
					end,
					min = 6,
					max = 64,
					step = 2,
				},
                scale = {
                    type = 'range',
                    name = L["Scale"],
                    desc = L["Change the scale of the bars"],
                    order = 122,
                    min = 0.5,
                    max = 2,
                    get = function()
                        return Scorchio.db.profile.baroptions.scale
                    end,
                    set = function(v)
                        Scorchio.db.profile.baroptions.scale = v
                        if testBars then Scorchio:ShowTestBars() end
                    end
                },
                barcolour = {
                    type = 'color',
                    name = L["Bar Colour"],
                    desc = L["Change bar colour"],
                    order = 110,
                    get = function()
                        return unpack(Scorchio.db.profile.baroptions.fgcolours)
                    end,
                    set = function(r, g, b, a)
                        Scorchio.db.profile.baroptions.fgcolours = {r, g, b, a}
                        if testBars then Scorchio:ShowTestBars() end
                    end,
                    hasAlpha = true
                },
                backgroundcolour= {
                    type = 'color',
                    name = L["Background Colour"],
                    desc = L["Change background colour"],
                    order = 111,
                    get = function()
                        return unpack(Scorchio.db.profile.baroptions.bgcolours)
                    end,
                    set = function(r, g, b, a)
                        Scorchio.db.profile.baroptions.bgcolours = {r, g, b, a}
                        if testBars then Scorchio:ShowTestBars() end
                    end,
                    hasAlpha = true
                },
                texture = {
                    type = 'text',
                    name = L["Texture"],
                    desc = L["Change the texture of the bars"],
                    order = 112,
                    get = function() 
                        return Scorchio.db.profile.baroptions.texture 
                    end,
                    set = function(v)
                        Scorchio.db.profile.baroptions.texture = v
                        if testBars then Scorchio:ShowTestBars() end
                    end,
                    validate = SM:List("statusbar")
                },                
                fadetime = {
                    type = 'range',
                    name = L["Fade Time"],
                    desc = L["Change how long the bars remain after a vulnerability has faded. (-1 will stop them disappearing until you leave combat or the mob is rescorched)"],
                    min = -1,
                    max = 30,
                    step = 1,
                    get = function()
                        return Scorchio.db.profile.baroptions.fadetime
                    end,
                    set = function(v)
                        Scorchio.db.profile.baroptions.fadetime = v
                    end
                },
                icon = {
                    type = 'group',
                    name = L["Icon"],
                    desc = L["Show Scorchio! icon beside bars"],
                    args = {
                        iconshow = {
                            type = 'toggle',
                            name = L["Show"],
                            desc = L["Show Scorchio! icon beside bars"],
                            order = 100,
                            get = function()
                                return Scorchio.db.profile.baroptions.iconshow
                            end,
                            set = function(v)
                                Scorchio.db.profile.baroptions.iconshow = not Scorchio.db.profile.baroptions.iconshow
                                if testBars then Scorchio:ShowTestBars() end
                            end
                        },
                        iconside = {
                            type = 'text',
                            name = L["Side"],
                            disabled = function()
                                return not Scorchio.db.profile.baroptions.iconshow
                            end,
                            desc = L["Show Scorchio! icon on left or right of bars"],
                            order = 101,
                            get = function() 
                                return Scorchio.db.profile.baroptions.iconside 
                            end,
                            set = function(v)
                                Scorchio.db.profile.baroptions.iconside = v
                                if testBars then Scorchio:ShowTestBars() end
                            end,
                            validate = { ["LEFT"] = L["Left"], ["RIGHT"] = L["Right"] }
                        },
                        casting = {
                            type = 'group',
                            name = L["Cast Indicator"],
                            desc = L["Show whether someone is currently casting a scorch on a mob"],
                            disabled = function()
                                return not Scorchio.db.profile.baroptions.iconshow
                            end,
                            order = 102,
                            args = {
                                castshow = {
                                    type = 'toggle',
                                    name = L["On"],
                                    desc = L["Use icons as casting indicators"],
                                    get = function()
                                        return Scorchio.db.profile.baroptions.casting.on
                                    end,
                                    set = function(v)
                                        Scorchio.db.profile.baroptions.casting.on =  not Scorchio.db.profile.baroptions.casting.on
                                    end
                                },
                                castshowself = {
                                    type = 'toggle',
                                    name = L["Show Self"],
                                    desc = L["Show you own casting on the icons"],
                                    disabled = function()
                                        return not Scorchio.db.profile.baroptions.casting.on
                                    end,
                                    get = function()
                                        return Scorchio.db.profile.baroptions.casting.self
                                    end,
                                    set = function(v)
                                        Scorchio.db.profile.baroptions.casting.self =  not Scorchio.db.profile.baroptions.casting.self
                                    end
                                },
                            },
                        },                                    
                    },
                },
            },
        },
        syncreceive = {
            type = 'group',
            name = L["Receive Data"],
            desc = L["Change sync data sources to listen to"],
            args = {
                scorchio = {
                    type = 'toggle',
                    name = L["Scorchio! Sync"],
                    desc = L["Receive data from other Scorchio! users"],
                    get = function()
                        return Scorchio.db.profile.syncreceive.scorchio
                    end,
                    set = function()
                        Scorchio.db.profile.syncreceive.scorchio = not Scorchio.db.profile.syncreceive.scorchio
                    end
                },
                events = {
                    type = 'toggle',
                    name = L["Local Events"],
                    desc = L["Receive data from combat log events within range"],
                    get = function()
                        return Scorchio.db.profile.syncreceive.events
                    end,
                    set = function()
                        Scorchio.db.profile.syncreceive.events = not Scorchio.db.profile.syncreceive.events
                    end
                },
            },
        },
        warningtime = {
            type = 'range',
            name = L["Warning Time"],
            desc = L["Length of time to be warned before Fire Vulnerability expires. (Set to 0 to disable)"],
            min = 0,
            max = 30,
            step = 1,
            get = function ()
                return Scorchio.db.profile.warningtime
            end,
            set = function(v)
                Scorchio.db.profile.warningtime = v
            end
        },
        sounds = {
            type = 'group',
            name = L["Sounds"],
            desc = L["Notification Sounds"],
            args = {
                    on = {
                    type = 'toggle',
                    name = L["Toggle Sounds"],
                    desc = L["Enable/Disable all sounds"],
                    order = 110,
                    get = function()
                        return Scorchio.db.profile.sounds.on
                    end,
                    set = function()
                        Scorchio.db.profile.sounds.on = not Scorchio.db.profile.sounds.on
                    end
                },
                warningsound = {
                    type = 'text',
                    name = L["Warning Sound"],
                    disabled = function()
                        return not Scorchio.db.profile.sounds.on
                    end,
                    desc = L["Change the sound played when warning time is reached"],
                    order = 111,
                    get = function() 
                        return Scorchio.db.profile.sounds.warningsound 
                    end,
                    set = function(v)
                        Scorchio.db.profile.sounds.warningsound = v
                        PlaySoundFile(SM:Fetch("sound",v))
                    end,
                    validate = SM:List("sound")
                },
                expiredsound = {
                    type = 'text',
                    name = L["Expired Sound"],
                    disabled = function()
                        return not Scorchio.db.profile.sounds.on
                    end,
                    desc = L["Change the sound played when Fire Vulnerability expires"],
                    order = 112,
                    get = function() 
                        return Scorchio.db.profile.sounds.expiredsound 
                    end,
                    set = function(v)
                        Scorchio.db.profile.sounds.expiredsound = v
                        PlaySoundFile(SM:Fetch("sound",v))
                    end,
                    validate = SM:List("sound")
                },
            },
        },
        blacklist = {
            type = 'group',
            name = L["Blacklist"],
            desc = L["Blacklist mages who aren't 3/3 Imp Scorch"],
            args = {
                magelist = {
                    type = 'text',
                    name = L["Blacklist"],
                    order = 100,
                    desc = L["Blacklist mages who aren't 3/3 Imp Scorch. (Check mages to ignore their data)"],
                    get = function(key)
                        return Scorchio.db.profile.blacklist[key]
                    end,
                    set = function(key,value)
                        Scorchio.db.profile.blacklist[key] = value
                    end,
                    multiToggle = true,
                    validate = mageList
                },
                autoblacklist = {
                    type = 'toggle',
                    name = L["Automatic"],
                    desc = L["Check to automatically blacklist mages in your party without 3/3 Imp Scorch"],
                    order = 105,
                    get = function()
                        return Scorchio.db.profile.autoBlackList
                    end,
                    set = function()
                        Scorchio.db.profile.autoBlackList = not Scorchio.db.profile.autoBlackList
                        Scorchio:RebuildMageList()
                    end
                },
                rebuild = {
                    type = 'execute',
                    name = L["Rebuild"],
                    desc = L["Rebuild Mage List"],
                    order = 110,
                    func = "RebuildMageList"
                },
            },
        },
        debug = {
            type = 'group',
            name = "Debug",
            desc = "Debug Options",
            guiHidden = true,
            args = {
                duplicates = {
                    type = 'toggle',
                    name = "Duplicates",
                    desc = "Notify of duplicate supression.",
                    get = function()
                        return Scorchio.db.profile.debug.duplicates
                    end,
                    set = function()
                        Scorchio.db.profile.debug.duplicates = not Scorchio.db.profile.debug.duplicates
                    end
                },
                sync = {
                    type = 'toggle',
                    name = "Sync Info",
                    desc = "Display synchronisation debug information",
                    get = function()
                        return Scorchio.db.profile.debug.sync
                    end,
                    set = function()
                        Scorchio.db.profile.debug.sync = not Scorchio.db.profile.debug.sync
                    end                   
                },
                mob = {
                    type = 'toggle',
                    name = "Mob Info",
                    desc = "Display mob debug information",
                    get = function()
                        return Scorchio.db.profile.debug.mob
                    end,
                    set = function()
                        Scorchio.db.profile.debug.mob = not Scorchio.db.profile.debug.mob
                    end
                },
                code = {
                    type = 'toggle',
                    name = "Code Info",
                    desc = "Display code debug information",
                    get = function()
                        return Scorchio.db.profile.debug.code
                    end,
                    set = function()
                        Scorchio.db.profile.debug.code = not Scorchio.db.profile.debug.code
                    end
                },
                timers = {
                    type = 'toggle',
                    name = "Timers Info",
                    desc = "Display timers debug information",
                    get = function()
                        return Scorchio.db.profile.debug.timers
                    end,
                    set = function()
                        Scorchio.db.profile.debug.timers = not Scorchio.db.profile.debug.timers
                    end
                },                  
            },
        },
    },
}

Scorchio = AceLibrary("AceAddon-2.0"):new("AceComm-2.0", "AceConsole-2.0", "AceDB-2.0", "AceEvent-2.0", "CandyBar-2.0", "FuBarPlugin-2.0", "Sink-1.0")

Scorchio:RegisterChatCommand("/scorchio", options)
Scorchio.OnMenuRequest = options

Scorchio:RegisterDB("ScorchioDB", "ScorchioDBPC")
Scorchio:RegisterDefaults("profile", {
        sink10OutputSink = "ChatFrame",
        baroptions = {
            barposition = {0, 50},
            p = "CENTER",
            rP = "CENTER",
            scale = 1.0,
            fadetime = -1,
            iconshow = true,
            iconside = "LEFT",
            casting = {
                on = true,
                self = false,
            },
            fgcolours = { 0, 1, 0, 0.7 },
            bgcolours = { 1, 0, 0, 0.7 },
            texture = "Blizzard",
            width = 192,
            height = 16
        },
        syncreceive = {
            scorchio = true,
            events = true
        },
        warningtime = 6,
        debug = {
            duplicates = false,
            sync = false,
            mob = false,
            code = false,
            timers = false
        },
        sounds = {
            on = true,
            warningsound = "Bell",
            expiredsound = "Info"
        },
        blacklist = { },
        autoBlackList = false
	}
)

Scorchio:SetCommPrefix("Scorchio")

Scorchio.hasIcon = "Interface\\AddOns\\Scorchio\\icons\\scorch"

local function Debug(class, msg)
    local text = "DEBUG: " .. msg
    if Scorchio.db.profile.debug[class] then
        Scorchio:Print(text)
    end
end
Scorchio.Debug = Debug

local function hasImpScorch()
    local nameTalent,_,_,_,currRank,_ = GetTalentInfo(2,10)
    if nameTalent == "Improved Scorch" and currRank == 3 then
        return true
    else
        return false
    end
end

Scorchio.hasImpScorch = hasImpScorch

function Scorchio:OnClick()
    self:ToggleAnchor()
end

function Scorchio:InitializeTables()
    scorchTable = { }
    casterTable = { }
    cleanTable = { }
end

function Scorchio:OnInitialize()
end

function Scorchio:OnEnable()
    self:RegisterComm(self.commPrefix, "GROUP", "ReceiveMessage")
    self:RegisterComm(self.commPrefix, "WHISPER", "ReceiveMessage")
    self:SetDefaultCommPriority("ALERT")
--	self:RegisterEvent("CHAT_MSG_SPELL_SELF_DAMAGE")
--	self:RegisterEvent("CHAT_MSG_SPELL_PARTY_DAMAGE")
--	self:RegisterEvent("CHAT_MSG_SPELL_FRIENDLYPLAYER_DAMAGE")
--	self:RegisterEvent("UNIT_SPELLCAST_SENT")
--	self:RegisterEvent("UNIT_SPELLCAST_STOP")
--	self:RegisterEvent("CHAT_MSG_COMBAT_HOSTILE_DEATH")
	self:RegisterEvent("PLAYER_REGEN_ENABLED")
	self:RegisterEvent("PARTY_MEMBERS_CHANGED")
	self:RegisterEvent("TIMER_COMPLETE", "TimerComplete")
--Sent Edit!
self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
--
    self.anchor = self:CreateAnchor()
    self:RegisterCandyBarGroup(SB)
    self:SetGrowUp()
    self:InitializeTables()
    if Scorchio.db.profile.blacklist[playerName] == nil then 
        Scorchio.db.profile.blacklist[playerName] = not hasImpScorch() 
        Debug("code", "Adding " .. tostring(playerName) .. " to the Blacklist as " .. tostring(Scorchio.db.profile.blacklist[playerName]))
    end
    self:RebuildMageList()
    castingScorch = false
end

function Scorchio:OnDisable()
end

function Scorchio:ShowTestBars()
    for c = 1,2 do
        local name = "Test" .. c
        self:RegisterCandyBar(name, 30 / c, name)
        self:RegisterCandyBarWithGroup(name, SB)
        self:SetCandyBarColor(name, unpack(Scorchio.db.profile.baroptions.fgcolours))
        self:SetCandyBarBackgroundColor(name, unpack(Scorchio.db.profile.baroptions.bgcolours))
        self:SetCandyBarFade(name, Scorchio.db.profile.baroptions.fadetime)
        if Scorchio.db.profile.baroptions.iconshow then
            self:SetCandyBarIcon(name,"Interface\\AddOns\\Scorchio\\icons\\scorchr" .. c)
            self:SetCandyBarIconPosition(name,Scorchio.db.profile.baroptions.iconside)
        else
            self:SetCandyBarIcon(name, nil)
        end
        self:SetCandyBarWidth(name, Scorchio.db.profile.baroptions.width)
        self:SetCandyBarHeight(name, Scorchio.db.profile.baroptions.height)
        self:SetCandyBarScale(name, Scorchio.db.profile.baroptions.scale)
        self:SetCandyBarTexture(name, SM:Fetch("statusbar", Scorchio.db.profile.baroptions.texture))
        self:StartCandyBar(name)
        testBars = true
    end
end

function Scorchio:HideTestBars()
       for c = 1,2 do
            local name = "Test" .. c
            self:UnregisterCandyBarWithGroup(name,SB)
            self:UnregisterCandyBar(name)
        end
        testBars = false
    end

function Scorchio:ToggleAnchor()
	if self.anchor:IsVisible() then
		self.anchor:Hide()
        self:HideTestBars()
	else
		self.anchor:Show()
        self:ShowTestBars()
	end
    Debug("code","Anchor position: " .. tostring(Scorchio.db.profile.baroptions.barposition.x) .. ", " .. tostring(Scorchio.db.profile.baroptions.barposition.y))
end

function Scorchio:CreateAnchor()
	local f = CreateFrame("Button", nil, UIParent)
		f:SetWidth(160)
		f:SetHeight(25)
		
		f.owner = self
		
		if Scorchio.db.profile.baroptions.barposition.x and Scorchio.db.profile.baroptions.barposition.y and Scorchio.db.profile.baroptions.barposition.p and Scorchio.db.profile.baroptions.barposition.rP then
		    f:ClearAllPoints()
			f:SetPoint(Scorchio.db.profile.baroptions.barposition.p, UIParent, Scorchio.db.profile.baroptions.barposition.rP, Scorchio.db.profile.baroptions.barposition.x, Scorchio.db.profile.baroptions.barposition.y)
		else
            f:SetPoint("CENTER", UIParent, "CENTER", 0, 50)
		end
	
		f:SetScript("OnDragStart", function() this:StartMoving() end )
		f:SetScript("OnDragStop",
			function()
				this:StopMovingOrSizing()
				local p, _, rP, x, y = this:GetPoint()
				Scorchio.db.profile.baroptions.barposition.x = math.floor(x)
				Scorchio.db.profile.baroptions.barposition.y = math.floor(y)
                Scorchio.db.profile.baroptions.barposition.p = p
                Scorchio.db.profile.baroptions.barposition.rP = rP
            end)
	
		f:SetBackdrop({bgFile = "Interface/Tooltips/UI-Tooltip-Background",
	                                            edgeFile = "Interface/Tooltips/UI-Tooltip-Border",
	                                            tile = false, tileSize = 16, edgeSize = 16,
	                                            insets = { left = 5, right =5, top = 5, bottom = 5 }})
		f:SetBackdropColor(1,0,0,.6)
		f:SetMovable(true)
		f:RegisterForDrag("LeftButton")
	
		f.Text = f:CreateFontString(nil, "OVERLAY")
		f.Text:SetFontObject(GameFontNormalSmall)
		f.Text:ClearAllPoints()
		f.Text:SetTextColor(1, 1, 1, 1)
		f.Text:SetWidth(160)
		f.Text:SetHeight(25)
		f.Text:SetPoint("TOPLEFT", f, "TOPLEFT")
		f.Text:SetJustifyH("CENTER")
		f.Text:SetJustifyV("MIDDLE")
		f.Text:SetText("Scorchio! v" .. versionNumber)
		f:Hide()
	return f
end

function Scorchio:ResetAnchor()
    self.db.profile.baroptions.barposition.x = 0
    self.db.profile.baroptions.barposition.y = 50
    Scorchio.db.profile.baroptions.barposition.p = "CENTER"
    Scorchio.db.profile.baroptions.barposition.rP = "CENTER"
    self.anchor:ClearAllPoints()
    self.anchor:SetPoint("CENTER", UIParent, "CENTER", 0, 50)
    self.anchor:Show()
    self:ShowTestBars()
end

function Scorchio:SetGrowUp()
	if Scorchio.db.profile.growUp then
		self:SetCandyBarGroupPoint(SB, "BOTTOM", self.anchor, "TOP", -7, 0)
		self:SetCandyBarGroupGrowth(SB, true)
        if testBars then self:ShowTestBars() end
	else
		self:SetCandyBarGroupPoint(SB, "TOP", self.anchor, "BOTTOM", -7, 0)
		self:SetCandyBarGroupGrowth(SB, false)
        if testBars then self:ShowTestBars() end
	end
end

function Scorchio:COMBAT_LOG_EVENT_UNFILTERED(timestamp, event, _, srcName, _, destGUID, destName, _, _, spellName, _, _, _, resisted)
    if (event == "SPELL_DAMAGE" and spellName == "Scorch" and srcName == playerName) then
		castTime = GetTime()
        Debug("code", tostring(playerName) .. ": " .. tostring(casterTable[playerName]) .. ", " .. tostring(castTime) .. " SELF")
        if casterTable[playerName] == nil or casterTable[playerName] < castTime - 1.2 then
            if not Scorchio.db.profile.blacklist[playerName] then
                Debug("sync", ">: " .. tostring(playerName) .. ", " .. tostring(destName))
                self:SendCommMessage("GROUP", playerName, destName, "SSYN")
                casterTable[playerName] = castTime
                self:UpdateTableScorch(destName, castTime)
                self:CreateBar(scorchTable[destName])
            else
                Debug("sync", tostring(playerName) .. " blacklisted. Ignoring event.")
            end
        else
            Debug("duplicates", "Duplicate event ignored (" .. tostring(playerName) ..") SELF")
        end 
	elseif event == "UNIT_DIED" then
		if scorchTable[destName] ~= nil then
			Debug("mob", tostring(destName) .. " dies.")
			scorchTable[destName] = nil
			self:UnregisterCandyBarWithGroup(destName,SB)
			self:UnregisterCandyBar(destName)
			Debug("sync", ">RDEA: " .. tostring(destName))
			self:SendCommMessage("GROUP", playerName, destName, "RDEA")
		end
    end
end

function Scorchio:CHAT_MSG_SPELL_SELF_DAMAGE(msg)
	local spell1 = string.match(arg1,'Your (.+) crits')
	local spell2 = string.match(arg1,'Your (.+) hits')
    local mob = string.match(arg1,'^.+its (.+) for')
    castTime = GetTime()
    if (spell1 == "Scorch" or spell2 == "Scorch") then
        Debug("code", tostring(playerName) .. ": " .. tostring(casterTable[playerName]) .. ", " .. tostring(castTime) .. " SELF")
        if casterTable[playerName] == nil or casterTable[playerName] < castTime - 1.2 then
            if not Scorchio.db.profile.blacklist[playerName] then
                Debug("sync", ">: " .. tostring(playerName) .. ", " .. tostring(mob))
                self:SendCommMessage("GROUP", playerName, mob, "SSYN")
                casterTable[playerName] = castTime
                self:UpdateTableScorch(mob, castTime)
                self:CreateBar(scorchTable[mob])
            else
                Debug("sync", tostring(playerName) .. " blacklisted. Ignoring event.")
            end
        else
            Debug("duplicates", "Duplicate event ignored (" .. tostring(playerName) ..") SELF")
        end 
    end
end

function Scorchio:CHAT_MSG_SPELL_PARTY_DAMAGE(msg)
    if not Scorchio.db.profile.syncreceive.events then return end
	local spell1 = string.match(arg1,"^.+ 's (.+) crits")
	local spell2 = string.match(arg1,"^.+ 's (.+) hits")
    local mob = string.match(arg1,'^.+its (.+) for')
    local caster = string.match(arg1,"^(.+) 's")
    local castTime = GetTime()
    if (spell1 == "Scorch" or spell2 == "Scorch") then
        Debug("code", tostring(caster) .. ": " .. tostring(casterTable[caster]) .. ", " .. tostring(castTime) .. " PARTY")
        if casterTable[caster] == nil or casterTable[caster] < castTime - 1.2 then
            if not Scorchio.db.profile.blacklist[caster] then 
                Debug("sync",">: " .. tostring(caster) .. ", " .. tostring(mob))
                self:SendCommMessage("GROUP", caster, mob, "SSYN") 
                casterTable[caster] = castTime
                self:UpdateTableScorch(mob, castTime)
                self:CreateBar(scorchTable[mob])
            else
                Debug("sync", tostring(caster) .. " blacklisted. Ignoring event.")
            end
        else
            Debug("duplicates", "Duplicate event ignored (" .. tostring(caster) ..") PARTY")
        end                
    end
end

function Scorchio:CHAT_MSG_SPELL_FRIENDLYPLAYER_DAMAGE(msg)
    if not Scorchio.db.profile.syncreceive.events then return end
	local spell1 = string.match(arg1,"^.+ 's (.+) crits")
	local spell2 = string.match(arg1,"^.+ 's (.+) hits")
    local mob = string.match(arg1,'^.+its (.+) for')
    local caster = string.match(arg1,"^(.+) 's")
    local castTime = GetTime()
    if (spell1 == "Scorch" or spell2 == "Scorch") then
        Debug("code", tostring(caster) .. ": " .. tostring(casterTable[caster]) .. ", " .. tostring(castTime) .. " OTHER")
        if casterTable[caster] == nil or casterTable[caster] < castTime - 1.2 then
            if not Scorchio.db.profile.blacklist[caster] then 
                Debug("sync",">: " .. tostring(caster) .. ", " .. tostring(mob))
                self:SendCommMessage("GROUP", caster, mob, "SSYN") 
                casterTable[caster] = castTime
                self:UpdateTableScorch(mob, castTime)
                self:CreateBar(scorchTable[mob])
            else
                Debug("sync", tostring(caster) .. " blacklisted. Ignoring event.")
            end
        else
            Debug("duplicates", "Duplicate event ignored (" .. tostring(caster) ..") OTHER")
        end                
    end
end

function Scorchio:UNIT_SPELLCAST_SENT(msg)
    if arg1 ~= "player" or arg2 ~= "Scorch" then return end
    castingScorch = arg4
    if Scorchio.db.profile.baroptions.casting.self then Scorchio:UpdateTableCast(castingScorch, 1) end
    self:SendCommMessage("GROUP", 1, castingScorch, "CSTA")
    Debug("sync",">CSTA: " .. tostring(arg4))
    Debug("code", "Casting Scorch on " .. tostring(arg4) .." at " .. tostring(GetTime()))

end
    
function Scorchio:UNIT_SPELLCAST_STOP(msg)
    if arg1 ~= "player" or not castingScorch then return end
    if Scorchio.db.profile.baroptions.casting.self then Scorchio:UpdateTableCast(castingScorch, -1) end
    self:SendCommMessage("GROUP", -1, castingScorch, "CSTO")
    Debug("sync", ">CSTO: " .. tostring(castingScorch))
    Debug("code", "Finished casting Scorch at " .. tostring(GetTime()))
    castingScorch = false
end    

function Scorchio:ReceiveMessage(prefix, sender, distribution, arg1, arg2, arg3)
    if arg3 == nil or arg3 == "SSYN" then
        if not Scorchio.db.profile.syncreceive.scorchio then return end    
        local castTime = GetTime()
        local caster = arg1
        local mob = arg2
        Debug("sync", "<: " .. tostring(caster) .. ", " .. tostring(mob))
        Debug("code", tostring(caster) .. ": " .. tostring(casterTable[caster]) .. ", " .. tostring(castTime) .. " SYNC")
        if casterTable[caster] == nil or casterTable[caster] < castTime - 1.2 then
            if not Scorchio.db.profile.blacklist[caster] then
                casterTable[caster] = castTime
                self:UpdateTableScorch(mob, GetTime())
                self:CreateBar(scorchTable[mob])
            else
                Debug("sync", tostring(caster) .. " blacklisted. Ignoring event.")
            end
        else
            Debug("duplicates", "Duplicate event ignored (" .. tostring(caster) ..") SYNC")
        end
    end
    if arg3 == "CSTA" then
        if not Scorchio.db.profile.syncreceive then return end
        if not Scorchio.db.profile.blacklist[caster] then
            local mob = arg2
            Scorchio:UpdateTableCast(mob, 1)
            Debug("sync", "<CSTA: " .. tostring(sender))
        end
    end
    if arg3 == "CSTO" then
        if not Scorchio.db.profile.syncreceive then return end
        if not Scorchio.db.profile.blacklist[caster] then
            local mob = arg2
            Scorchio:UpdateTableCast(mob, -1)
            Debug("sync", "<CSTO: " .. tostring(sender))
        end
    end
    if arg3 == "RDEA" then
        if not Scorchio.db.profile.syncreceive then return end
        local mob = arg2
        if scorchTable[mob] ~= nil then
            Debug("mob", tostring(mob) .. " dies.")
            scorchTable[mob] = nil
            self:UnregisterCandyBarWithGroup(mob,SB)
            self:UnregisterCandyBar(mob)
        end
    end
    if arg3 == "RTAL" then 
        Debug("sync", "<RTAL: " .. tostring(sender))
        self:SendCommMessage("WHISPER", sender, playerName, hasImpScorch(), "STAL")
    end
    if arg3 == "STAL" then
        local caster = arg1
        local remImpScorch = arg2
        Debug("sync", "<STAL: " .. tostring(sender))
        Scorchio.db.profile.blacklist[caster] = not remImpScorch
        Debug("code", "Adding " .. tostring(caster) .. " to the Blacklist as " .. tostring(Scorchio.db.profile.blacklist[caster]))
    end
end

function Scorchio:CHAT_MSG_COMBAT_HOSTILE_DEATH(msg)
	local mob = string.match(arg1,'(.+) is slain by')
	if (mob == nil) then
        mob = string.match(arg1,'You have slain (.+)!')
  	end
	if (mob == nil) then
	    mob = string.match(arg1,'(.+) is destroyed.')
	end
	if (mob == nil) then
		mob = string.match(arg1,'(.+) dies.')
	end
    if mob ~= nil and scorchTable[mob] ~= nil then
        Debug("mob", tostring(mob) .. " dies.")
        scorchTable[mob] = nil
        self:UnregisterCandyBarWithGroup(mob,SB)
        self:UnregisterCandyBar(mob)
        Debug("sync", ">RDEA: " .. tostring(mob))
        self:SendCommMessage("GROUP", playerName, mob, "RDEA")
    end
end

function Scorchio:PLAYER_REGEN_ENABLED()
    for k,v in pairs(scorchTable) do
        self:UnregisterCandyBarWithGroup(k,SB)
        self:UnregisterCandyBar(k)
    end
    for k,v in pairs(cleanTable) do
        self:UnregisterCandyBarWithGroup(k,SB)
        self:UnregisterCandyBar(k)
    end
    self:InitializeTables()
end

function Scorchio:PARTY_MEMBERS_CHANGED()
    Scorchio:RebuildMageList()
end

function Scorchio:RebuildMageList()
    local tmp = { }
    local count = 0
    local ceiling = GetNumRaidMembers()
    local rop = "raid"
    if ceiling == 0 then 
        ceiling = GetNumPartyMembers()
        rop = "party"
        tmp = { playerName }
        count = count + 1
    end
    if ceiling == 0 then
        mageList = { playerName }
        options.args.blacklist.args.magelist.validate = mageList
        return
    end
    for i = 1, ceiling do
        local unit = rop..tostring(i)
        local _, unitclass = UnitClass(unit)
        local unitname, unitrealm
        if unitclass == "MAGE" then
            unitname, unitrealm = UnitName(unit)
            if unitrealm ~= nil then
                Debug("code",":"..unitname..":-:"..unitrealm..":")
                unitrealm = "-" .. unitrealm
                if unitrealm ~= "-" then unitname = unitname .. unitrealm end
            end
            table.insert(tmp, unitname)
            count = count + 1
        end
    end
    mageList = tmp
    for k,v in pairs(mageList) do
        if Scorchio.db.profile.blacklist[v] == nil then
            Scorchio.db.profile.blacklist[v] = false
            Debug("code", "New mage: " .. tostring(v))
        end
        if Scorchio.db.profile.autoBlackList then
            self:SendCommMessage("WHISPER", v, playerName, hasImpScorch(), "RTAL")
            Debug("sync",">RTAL: " .. tostring(v))
        end
    end
    Debug("code",tostring(count) .. " mages added.")
    options.args.blacklist.args.magelist.validate = mageList
end
    
function Scorchio:UpdateTableScorch(mob, time)
    if scorchTable[mob] == nil then
        Debug("mob", "New mob: " .. tostring(mob))
        scorchTable[mob] = { mob, GetTime(), 1 , 0}
    else
        local scorchStack = scorchTable[mob][SCORCHSTACK]
        if scorchStack < 5 then
            scorchStack = scorchStack + 1
        end
        scorchTable[mob][REFRESHTIME] = time
        scorchTable[mob][SCORCHSTACK] = scorchStack
    end
    if Scorchio.db.profile.warningtime > 0 and scorchTable[mob][SCORCHSTACK] > 0 then Scorchio:ScheduleEvent("TIMER_COMPLETE",(30 - Scorchio.db.profile.warningtime), mob) end
end

function Scorchio:UpdateTableCast(mob, flag)
    if not Scorchio.db.profile.baroptions.casting.on then return end
    Debug("code", "FLAG: " .. tostring(mob) .. ", " .. tostring(flag))
    if flag == 1 then
        if scorchTable[mob] == nil then
            Debug("mob", "New mob: " .. tostring(mob))
            scorchTable[mob] = { mob, GetTime(), 0 , 1}
        else
            scorchTable[mob][CASTS] = scorchTable[mob][CASTS] + 1
        end
    else
        if flag == -1 then
            if scorchTable[mob] == nil or scorchTable[mob][CASTS] < 1 then
                return
            else
                scorchTable[mob][CASTS] = scorchTable[mob][CASTS] - 1
            end
        end
    end
    if not self.db.profile.baroptions.iconshow then return end
    local scorchStack = scorchTable[mob][SCORCHSTACK]
    local casts = scorchTable[mob][CASTS]
    Debug("code", "CASTS: " .. tostring(mob) .. ", " .. tostring(casts))
    if scorchStack > 0 then
        if casts > 0 then
            self:SetCandyBarIcon(mob,"Interface\\AddOns\\scorchio\\icons\\scorchg" .. scorchStack)
        else
            self:SetCandyBarIcon(mob,"Interface\\AddOns\\scorchio\\icons\\scorchr" .. scorchStack)
        end
    end
end 

function Scorchio:TimerComplete(mob)
    local timertime = GetTime()
    if scorchTable[mob] then
        Debug("timers", "TIMER: " ..tostring(mob) .. ", " .. tostring(scorchTable[mob][REFRESHTIME]) .. ", " .. tostring(timertime) .. ", " .. tostring(scorchTable[mob][REFRESHTIME] - timertime))
        if scorchTable[mob][REFRESHTIME] - timertime < (-30 + Scorchio.db.profile.warningtime) then
            if Scorchio.db.profile.sounds.on then
                PlaySoundFile(SM:Fetch("sound", Scorchio.db.profile.sounds.warningsound))
            end
            self:Pour(L["Rescorch "] .. mob .. "!", 1, 0.647, 0)
        end
    end
end

function Scorchio:iconColour(scorchTarget)
    if scorchTarget == nil or scorchTarget[CASTS] == 0 then
        return "r"
    else
        return "g"
    end
end

function Scorchio:CreateBar(scorchTarget)
    local mob = scorchTarget[MOBNAME]
    local elapsedTime = GetTime() - scorchTarget[REFRESHTIME]
	local remainingTime = math.floor (30 - elapsedTime)
    local scorchStack = scorchTarget[SCORCHSTACK]
    local text = "(x" .. scorchStack .. ")  " .. mob
    local name = mob
    local ExpFun = function (mob)
        if Scorchio.db.profile.sounds.on then
            PlaySoundFile(SM:Fetch("sound", Scorchio.db.profile.sounds.expiredsound))
        end
        self:Pour(L["Fire Vulnerability Expired on "] .. mob, 1, 0, 0)
        cleanTable[mob] = true
        scorchTable[mob] = nil
    end
    self:RegisterCandyBar(name, remainingTime, text)
    self:RegisterCandyBarWithGroup(name, SB)
    self:SetCandyBarColor(name, unpack(Scorchio.db.profile.baroptions.fgcolours))
    self:SetCandyBarBackgroundColor(name, unpack(Scorchio.db.profile.baroptions.bgcolours))
    self:SetCandyBarFade(name, Scorchio.db.profile.baroptions.fadetime)
    if Scorchio.db.profile.baroptions.iconshow then
        self:SetCandyBarIcon(name,"Interface\\AddOns\\scorchio\\icons\\scorch" .. Scorchio:iconColour(scorchTarget) .. scorchStack)
        self:SetCandyBarIconPosition(name,Scorchio.db.profile.baroptions.iconside)
    else
        self:SetCandyBarIcon(name, nil)
    end
    self:SetCandyBarWidth(name, Scorchio.db.profile.baroptions.width)
    self:SetCandyBarHeight(name, Scorchio.db.profile.baroptions.height)
    self:SetCandyBarScale(name, Scorchio.db.profile.baroptions.scale)
    self:SetCandyBarTexture(name, SM:Fetch("statusbar", Scorchio.db.profile.baroptions.texture))
    self:SetCandyBarCompletion(name, ExpFun, mob)
    self:StartCandyBar(name)
end
